package com.xiaozhaovip.demo.controller;

import com.xiaozhaovip.demo.Enum.*;
import com.xiaozhaovip.demo.controller.util.AliyunOSSClientUtils;
import com.xiaozhaovip.demo.controller.util.IpUtils;
import com.xiaozhaovip.demo.intf.DO.ResponseDO;
import com.xiaozhaovip.demo.intf.entity.YueQiLaiActivityCollect;
import com.xiaozhaovip.demo.intf.entity.YueQiLaiActivityJoiner;
import com.xiaozhaovip.demo.intf.entity.YueQiLaiInfo;
import com.xiaozhaovip.demo.intf.entity.YueQiLaiUser;
import com.xiaozhaovip.demo.intf.service.YueQiLaiActivityCollectService;
import com.xiaozhaovip.demo.intf.service.YueQiLaiActivityJoinerService;
import com.xiaozhaovip.demo.intf.service.YueQiLaiInfoService;
import com.xiaozhaovip.demo.intf.service.YueQiLaiUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 活动信息 控制层
 *
 * @author Cauli
 */
@Slf4j
@RestController
@RequestMapping("/yueQiLai/activity/info")
public class YueQiLaiInfoController extends BaseController {
    @Resource
    private YueQiLaiInfoService yueQiLaiInfoService;

    @Resource
    private YueQiLaiActivityJoinerService yueQiLaiActivityJoinerService;

    @Resource
    private YueQiLaiActivityCollectService yueQiLaiActivityCollectService;

    @Resource
    private YueQiLaiUserService yueQiLaiUserService;

    @Resource
    private AliyunOSSClientUtils aliyunOSSClientUtils;

    /**
     * 模拟当前登录用户
     */
    private final int userId = 2;

    /**
     * 手机正则
     */
    Pattern p1 = Pattern.compile("(13\\d|14[579]|15[^4\\D]|17[^49\\D]|18\\d)\\d{8}");

    /**
     * 用于活动发布页面的初始化数据获取接口
     *
     * @return
     */
    @GetMapping("init")
    public ResponseDO init() {
        log.info("init activity info submit");
        // 调用方法
        List<YueQiLaiCategoryEnum> categoryEnumList = YueQiLaiCategoryEnum.getAllCategories();
        List<YueQiLaiCityEnum> cityEnumList = YueQiLaiCityEnum.getAllCities();

        // 返回值处理
        Map<String, Object> data = turnListIntoMap(categoryEnumList, cityEnumList);
        return new ResponseDO(true, SUCCESS, SUCCESS_CODE, data);
    }

    /**
     * 发布活动接口
     *
     * @param yueQiLaiInfo
     * @param request
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("submit")
    public ResponseDO submit(@RequestBody YueQiLaiInfo yueQiLaiInfo, HttpServletRequest request) {
        log.info("get yueQiLaiInfo ," + yueQiLaiInfo);
        //参数验证 validateParams（快速验证方法，返回info界面的内容校验结果）
        String ret = validateParams(yueQiLaiInfo);
        if (!StringUtils.equals(ret, SUCCESS)) {
            log.info("fail to verify info ," + ret);
            return new ResponseDO(false, ret, FAIL_CODE, null);
        }

        // 获得并设置用户Ip
        yueQiLaiInfo.setUserIp(IpUtils.getIpAddr(request));
        log.info("设置用户属性完成，准备进行活动发布 : " + yueQiLaiInfo);

        // 调用方法
        int insert = yueQiLaiInfoService.insert(yueQiLaiInfo);

        // 保证活动开始 前2小时 报名结束
        scheduledExecutor(yueQiLaiInfo.getBeginTime(), yueQiLaiInfo);

        // 返回值处理
        if (insert > 0) {
            Map<String, Object> data = new HashMap<>(1);
            data.put("insert", insert);
            return new ResponseDO(true, SUCCESS, 0, data);
        } else {
            return new ResponseDO(false, FAIL, 0, null);
        }
    }

    /**
     * 活动详情获取接口
     *
     * @param activityId
     * @return
     */
    @GetMapping("getById")
    public ResponseDO getById(int activityId) {
        // 参数验证
        if (activityId < 1) {
            return new ResponseDO(false, "活动id错误！", FAIL_CODE, null);
        }

        // 活动发布者
        int publishUserId;
        //是否参加活动 0：未参加 1：已参加
        int joinStatus;
        //收藏状态 0：未收藏 1：已收藏
        int collectStatus = 0;


        // 1 获取活动信息对象
        YueQiLaiInfo activityInfo = yueQiLaiInfoService.loadById(activityId);
        if (activityInfo == null) {
            return new ResponseDO(false, "活动内容不存在！", FAIL_CODE, null);
        } else {
            publishUserId = activityInfo.getPublishUserId();
        }
        // 2 获取活动的组织者对象
        YueQiLaiUser organizer = yueQiLaiUserService.selectById(publishUserId);

        // 3 获取参与该活动的用户对象 和 用户的报名状态
        YueQiLaiActivityJoiner yueQiLaiActivityJoiner = yueQiLaiActivityJoinerService.loadByUserIdAndActivityId(userId, activityId);
        YueQiLaiUser activityJoiner = yueQiLaiUserService.selectById(yueQiLaiActivityJoiner.getJoinerId());

        Map<String, Object> joiner = new HashMap<>(2);
        if (yueQiLaiActivityJoiner != null) {
            joinStatus = yueQiLaiActivityJoiner.getStatus();
            YueQiLaiActivityJoinerStatusEnum joinerStatusEnum = YueQiLaiActivityJoinerStatusEnum.getById(joinStatus);
            joiner.put("activityJoiner", activityJoiner);
            joiner.put("joinerStatusEnum", joinerStatusEnum);
        }

        // 4 获取用户对该活动的收藏状态
        YueQiLaiActivityCollect activityCollect = yueQiLaiActivityCollectService.loadByUserIdAndActivityId(userId, activityId);
        if (activityCollect != null) {
            collectStatus = activityCollect.getStatus();
        }

        // 处理返回值
        Map<String, Object> data = new HashMap<>(4);
        data.put("Organizer", organizer);
        data.put("Joiner", joiner);
        data.put("collectStatus", collectStatus);
        data.put("activityInfo", activityInfo);
        return new ResponseDO(true, SUCCESS, SUCCESS_CODE, data);
    }

    /**
     * 上传文件到阿里云oss接口
     *
     * @param files 1-4张图片文件
     * @return 用 “,” 拼接的图片名称
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("uploadPicture")
    public ResponseDO uploadPicture(MultipartFile[] files) {
        // 校验参数
        if (files == null || files.length < 1) {
            return new ResponseDO(false, "至少要上传1张活动图片！", FAIL_CODE, null);
        }
        if (files.length > 4) {
            return new ResponseDO(false, "图片数量不能超过4张！", FAIL_CODE, null);
        }

        // 上传文件到阿里云对象存储OSS
        List<Map<String, Object>> pictureList = aliyunOSSClientUtils.filesUpload(files);

        // 所有图片名称之间用 “,” 拼接
        StringBuilder images = new StringBuilder();
        for (Map<String, Object> map : pictureList) {
            if (images.length() == 0) {
                images.append(map.get("filePath"));
            } else {
                images.append(",").append(map.get("filePath"));
            }
        }
        // 处理返回值
        Map<String, Object> pictureNameMap = new HashMap<>(1);
        if (images.length() > 0) {
            pictureNameMap.put("images", images);
            return new ResponseDO(true, "图片上传成功！", SUCCESS_CODE, pictureNameMap);
        }
        return new ResponseDO(false, "图片上传到服务器失败！", FAIL_CODE, null);
    }

    /**
     * 对枚举list集合进行map封装
     *
     * @param categoryEnumList 所有分类枚举集合
     * @param cityEnumList     所有城市枚举集合
     * @return
     */
    private Map<String, Object> turnListIntoMap(List<YueQiLaiCategoryEnum> categoryEnumList, List<YueQiLaiCityEnum> cityEnumList) {
        List<Map<String, Object>> categoryList = new ArrayList<>();
        List<Map<String, Object>> cityList = new ArrayList<>();
        Map<String, Object> categoryEnumMap;
        Map<String, Object> cityEnumMap;

        for (YueQiLaiCategoryEnum categoryEnum : categoryEnumList) {
            categoryEnumMap = new HashMap<>(2);
            categoryEnumMap.put("id", categoryEnum.getId());
            categoryEnumMap.put("name", categoryEnum.getName());
            categoryList.add(categoryEnumMap);
        }
        for (YueQiLaiCityEnum cityEnum : cityEnumList) {
            cityEnumMap = new HashMap<>(2);
            cityEnumMap.put("id", cityEnum.getId());
            cityEnumMap.put("name", cityEnum.getName());
            cityList.add(cityEnumMap);
        }

        Map<String, Object> data = new HashMap<>(2);
        data.put("categoryEnumList", categoryList);
        data.put("cityEnumList", cityList);

        return data;
    }

    private String validateParams(YueQiLaiInfo info) {
        if (info == null) {
            return "活动信息不能为空";
        }
        if (StringUtils.isBlank(info.getTitle())) {
            return "活动标题不能是空";
        }
        if (info.getTitle().length() > 32) {
            return "活动标题长度不能大于32个字符";
        }
        if (YueQiLaiCategoryEnum.getById(info.getCategoryId()) == null) {
            return "分类信息不正确";
        }
        if (StringUtils.isBlank(info.getContent())) {
            return "活动内容不能为空";
        }
        if (info.getHighLight().length() > 150) {
            return "活动亮点不能超过150字";
        }
        Matcher m1 = p1.matcher(info.getContent());
        if (m1.find()) {
            return "活动详情不能包含联系方式";
        }
        if (YueQiLaiCityEnum.getById(info.getCityId()) == null) {
            return "城市信息不正确";
        }
        if (YueQiLaiTypeEnum.getById(info.getAddressType()) == null) {
            return "活动地址模式不正确";
        }
        if (info.getAddressType() == YueQiLaiTypeEnum.OffLine.getId() && StringUtils.isBlank(info.getAddress())) {
            return "线下活动地址不能为空";
        }
        if (!StringUtils.isBlank(info.getAddress()) && info.getAddress().length() > 100) {
            return "活动地址信息不能超过100字";
        }
        if (info.getLeastJoinNum() == 0) {
            return "最大人数输入无效";
        }
        if (info.getMostJoinNum() < info.getLeastJoinNum()) {
            return "最大人数小于最小人数";
        }
        if (info.getLeastJoinNum() < 0 || info.getLeastJoinNum() > 500) {
            return "活动人数不能超过500";
        }
        if (info.getBeginTime().compareTo(info.getEndTime()) > 0) {
            return "活动开始时间不能小于截止时间";
        }
        return SUCCESS;
    }

    /**
     * 活动时间到达活动开始前2小时，报名结束，修改活动状态
     *
     * @param beginTime
     * @param yueQiLaiInfo
     */
    private void scheduledExecutor(Date beginTime, YueQiLaiInfo yueQiLaiInfo) {
        // 设置最新自增id
        yueQiLaiInfo.setId(yueQiLaiInfoService.getLastInsertId());
        // 计算时间差
        long difference = Math.abs(beginTime.getTime() - System.currentTimeMillis()) - (2 * 60 * 60 * 1000);
        // 活动开始 前2小时 报名结束
        ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(10);
        scheduledExecutorService.schedule(() -> {
            // 修改活动状态SELECT
            log.info("活动时间到达活动开始前2小时，报名结束，修改活动状态！");
            yueQiLaiInfo.setStatus(YueQiLaiActivityStatusEnum.SignUpActivityClosed.getId());
            if (yueQiLaiInfoService.update(yueQiLaiInfo) > 0) {
                log.info("修改活动状态成功！");
            }
        }, difference, TimeUnit.MILLISECONDS);
    }
}
